from Products.Archetypes.public import *
from AccessControl import ClassSecurityInfo
from BTrees.IIBTree import IIBTree
from types import ListType, TupleType

from Products.ArchSurvey.questions.BaseSurveyQuestion import BaseSurveyQuestion, BaseSurveyItemsQuestion
from Products.ArchSurvey.questions import registerQuestion
from Products.ArchSurvey.Permissions import *
from Products.ArchSurvey.questions.schemata import *
from Products.ArchSurvey.widgets import SelectionWidgetPlus

class NumberQuestion(BaseSurveyQuestion):
    """A numeric question"""
    meta_type      = 'NumericQuestion'
    archetype_name = 'Numeric Question'
    shortDesc      = 'numeric'
    validators     = 'isInt'
    fieldType = IntegerField
    widgetType = IntegerWidget
    security = ClassSecurityInfo()
    
    def __init__(self, id, schemata, **kwargs):
        self._storage = IIBTree()
        self.field = self.fieldType(storage=ReadOnlyStorage(),schemata=schemata)
        self.setSchemata(schemata)
        BaseContentMixin.__init__(self, id, **kwargs)
    
    security.declareProtected(EDIT_CONTENT_PERMISSION, 'clearResults')
    def clearResults(self):
        """Clear results (e.g. to remove testing)"""
        self._storage = IIBTree()
    
    security.declareProtected(TAKE_SURVEY, 'addAnswer')
    def addAnswer(self, uid, answer):
        """Normalize answer into an int before inserting"""
        try:
            BaseSurveyQuestion.addAnswer(self, uid, int(answer))
        except ValueError:
            pass
    
    def getStats(self):
        vals = list(self._storage.values())
        if len(vals) > 0:
            mini = min(vals)
            maxi = max(vals)
        else:
            mini = None
            maxi = None
        return {'min': mini,
                'max': maxi}
    
class DateAndTimeQuestion(BaseSurveyQuestion):
    """A date/time question"""
    meta_type      = 'DateAndTimeQuestion'
    archetype_name = 'Date Time Question'
    shortDesc      = 'date/time'
    fieldType = DateTimeField
    widgetType = CalendarWidget
            
class ListQuestion(BaseSurveyQuestion):
    """A list question"""
    meta_type      = 'ListQuestion'
    archetype_name = 'List Question'
    shortDesc      = 'list'
    fieldType = LinesField
    widgetType = LinesWidget
    
class ShortAnswerQuestion(BaseSurveyQuestion):
    """A simple short answer question"""
    meta_type      = 'ShortAnswerQuestion'
    archetype_name = 'Survey Short Answer Question'
    shortDesc      = 'short answer'
    fieldType = StringField
    widgetType = StringWidget
    
class LabelQuestion(BaseSurveyQuestion):
    """A label (no actual question)"""
    schema = LabelSchema
    meta_type      = 'LabelQuestion'
    archetype_name = 'Label Question'
    shortDesc      = 'label'
    fieldType = StringField
    widgetType = LabelWidget

    def isLabel(self):
        return True

class LongAnswerQuestion(BaseSurveyQuestion):
    """A simple long answer question"""
    meta_type      = 'LongAnswerQuestion'
    archetype_name = 'Survey Long Answer Question'
    shortDesc      = 'long answer'
    fieldType = StringField
    widgetType = TextAreaWidget
    widgetProps = {'macro_edit':'textarea_survey_override'}
    
class PickOneQuestion(BaseSurveyItemsQuestion):
    """A pick-one question"""
    meta_type      = 'PickOneQuestion'
    archetype_name = 'Pick One Question'
    shortDesc      = 'pick one'
    fieldType = StringField
    widgetType = SelectionWidgetPlus
    schema = PickOneSchema
    widgetProps = {'macro_edit':'selection_survey_override'}

class PickManyQuestion(BaseSurveyItemsQuestion):
    """A pick-many question"""
    meta_type      = 'PickManyQuestion'
    archetype_name = 'Pick Many Question'
    shortDesc      = 'pick many'
    fieldType = LinesField
    widgetType = MultiSelectionWidget
    widgetProps = {'format':'checkbox'}
    security = ClassSecurityInfo()

    security.declareProtected(VIEW_RESULTS, 'getResults')
    def getResults(self):
        """Gets the results from all surveys"""
        results = {}
        for val_list in self._storage.values():
            for value in val_list:
                results[value] = results.get(value,0) + 1
        return [( item, results.get(item,0) ) for item in self.getVocabulary()]

    security.declareProtected(TAKE_SURVEY, 'isCorrectAnswer')
    def isCorrectAnswer(self, answer):
        """Are these answers correct?"""
        if type(answer) != type( [] ):
            answer = list( answer )
        my_answer = list(self.getAnswer())
        answer = filter( lambda x: x != '', answer )
        answer.sort()
        my_answer.sort()
        return answer == my_answer
 
class RankingsQuestion(BaseSurveyQuestion):
    """Rank a list of options"""
    meta_type      = 'RankingsQuestion'
    archetype_name = 'Rankings Question'
    shortDesc      = 'rankings'
    schema = BaseSurveyItemsQuestionSchema 
    fieldType = StringField
    widgetType = PicklistWidget
    security = ClassSecurityInfo()
    widgetProps = {'macro_edit':'picklist_survey_override'}

    security.declareProtected(VIEW_RESULTS, 'getResults')
    def getResults(self, type='Borda'):
        """Gets the results from all surveys"""
        results = {}
        for val_list in self._storage.values():
            for value in val_list:
                results[value] = results.get(value,0) + 1
        return [( item, results.get(item,0) ) for item in self.getVocabulary()]

##This one is still in process, yo!  That's why I don't register it!
class RatingsQuestion(BaseSurveyItemsQuestion):
    """Rate one or more items"""
    meta_type      = 'RatingsQuestion'
    archetype_name = 'Ratings Question'
    shortDesc      = 'ratings (1-5)'
    
    security = ClassSecurityInfo()

    security.declareProtected(VIEW_RESULTS, 'getResults')
    def getResults(self):
        """Gets the results from all surveys"""
        results = {}
        for val_list in self._storage.values():
            for value in val_list:
                results[value] = results.get(value,0) + 1
        return [( item, results.get(item,0) ) for item in self.getVocabulary()]

class YesNoQuestion(BaseSurveyQuestion):
    """A boolean question"""
    meta_type      = 'YesNoQuestion'
    archetype_name = 'Yes No Question'
    shortDesc      = 'yes/no'
    fieldType = BooleanField
    widgetType = BooleanWidget
    schema = YesNoSchema
    
    security = ClassSecurityInfo()
    
    def __init__(self, id, schemata, **kwargs):
        self._storage = IIBTree()
        self.field = self.fieldType(id, storage=ReadOnlyStorage(),schemata=schemata)
        self.setSchemata(schemata)
        BaseContentMixin.__init__(self, id, **kwargs)
    
    security.declareProtected(EDIT_CONTENT_PERMISSION, 'clearResults')
    def clearResults(self):
        """Clear results (e.g. to remove testing)"""
        self._storage = IIBTree()
    
    security.declareProtected(TAKE_SURVEY, 'addAnswer')
    def addAnswer(self, uid, answer):
        """Clean up answer before inserting 
        """
        answer = int(answer)
        if not answer:
            answer = 0
        else:
            answer = 1
        BaseSurveyQuestion.addAnswer(self, uid, answer)

registerQuestion(LongAnswerQuestion)
registerQuestion(ShortAnswerQuestion)
registerQuestion(LabelQuestion)
registerQuestion(PickOneQuestion)
registerQuestion(PickManyQuestion)
registerQuestion(YesNoQuestion)
registerQuestion(NumberQuestion)
registerQuestion(DateAndTimeQuestion)
registerQuestion(ListQuestion)
registerQuestion(RankingsQuestion)
